﻿namespace NJQuery {
	using System;
	using System.Diagnostics.CodeAnalysis;

	/// <summary>
	/// Defines a client script library to be registered with the jQuery <see cref="Manager"/> by various server controls.
	/// These entries are used to look up URLs in the <see cref="Configuration.ClientScriptsSection" /> of the config file or, in absence, to generate a default relative URL.
	/// </summary>
	public struct ClientScript : IEquatable<ClientScript> {


		#region Static Fields: Combined Script Definitions

		private static readonly ClientScript uiUnified = Settings.Current.ClientScripts.References.Contains("jquery.ui") ? new ClientScript("jquery.ui") : new ClientScript();

		#endregion


		#region Static Fields: Script Definitions

		/// <summary>
		/// The core <see href="http://jquery.com/">jQuery script library</see>.
		/// </summary>
		public static readonly ClientScript Core = new ClientScript("jquery");

		/// <summary>
		/// The core script library shared by the <see href="http://jqueryui.com/">jQuery UI</see> framework.
		/// </summary>
		public static readonly ClientScript UICore = new ClientScript("jquery.ui.core", uiUnified.name);

		/// <summary>
		/// The core script library shared by the widgets of the <see href="http://jqueryui.com/">jQuery UI</see> framework.
		/// </summary>
		public static readonly ClientScript UIWidgetFactory = new ClientScript("jquery.ui.widget", uiUnified.name);

		/// <summary>
		/// The core complex mouse library shared by the <see href="http://jqueryui.com/">jQuery UI</see> framework.
		/// </summary>
		public static readonly ClientScript UIMouseUtility = new ClientScript("jquery.ui.mouse", uiUnified.name);

		/// <summary>
		/// The core complex mouse library shared by the <see href="http://jqueryui.com/">jQuery UI</see> framework.
		/// </summary>
		public static readonly ClientScript UIPositionUtility = new ClientScript("jquery.ui.position", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/accordion/">jQuery UI Accordion widget</see>.
		/// </summary>
		public static readonly ClientScript UIAccordionWidget = new ClientScript("jquery.ui.accordion", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/autocomplete/">jQuery UI Autocomplete widget</see>.
		/// </summary>
		public static readonly ClientScript UIAutoCompleteWidget = new ClientScript("jquery.ui.autocomplete", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/button/">jQuery UI Button widget</see>.
		/// </summary>
		public static readonly ClientScript UIButtonWidget = new ClientScript("jquery.ui.button", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/datepicker/">jQuery UI Datepicker widget</see>.
		/// </summary>
		public static readonly ClientScript UIDatePickerWidget = new ClientScript("jquery.ui.datepicker", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/dialog/">jQuery UI Dialog widget</see>.
		/// </summary>
		public static readonly ClientScript UIDialogWidget = new ClientScript("jquery.ui.dialog", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/progressbar/">jQuery UI Progressbar widget</see>.
		/// </summary>
		public static readonly ClientScript UIProgressBarWidget = new ClientScript("jquery.ui.progressbar", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/slider/">jQuery UI Slider widget</see>.
		/// </summary>
		public static readonly ClientScript UISliderWidget = new ClientScript("jquery.ui.slider", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/tabs/">jQuery UI Tabs widget</see>.
		/// </summary>
		public static readonly ClientScript UITabsWidget = new ClientScript("jquery.ui.tabs", uiUnified.name);

		/// <summary>
		/// The core script library shared by the <see href="http://jqueryui.com/docs/Effects">jQuery UI Effects framework</see>.
		/// </summary>
		public static readonly ClientScript UIEffectsCore = new ClientScript("jquery.effects.core", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Blind">jQuery UI Blind effect</see>.
		/// </summary>
		public static readonly ClientScript UIBlindEffect = new ClientScript("jquery.effects.blind", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Bounce">jQuery UI Bounce effect</see>.
		/// </summary>
		public static readonly ClientScript UIBounceEffect = new ClientScript("jquery.effects.bounce", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Clip">jQuery UI Clip effect</see>.
		/// </summary>
		public static readonly ClientScript UIClipEffect = new ClientScript("jquery.effects.clip", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Drop">jQuery UI Drop effect</see>.
		/// </summary>
		public static readonly ClientScript UIDropEffect = new ClientScript("jquery.effects.drop", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Explode">jQuery UI Explode effect</see>.
		/// </summary>
		public static readonly ClientScript UIExplodeEffect = new ClientScript("jquery.effects.explode", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Fade">jQuery UI Fade effect</see>.
		/// </summary>
		public static readonly ClientScript UIFadeEffect = new ClientScript("jquery.effects.fade", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Fold">jQuery UI Fold effect</see>.
		/// </summary>
		public static readonly ClientScript UIFoldEffect = new ClientScript("jquery.effects.fold", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Highlight">jQuery UI Highlight effect</see>.
		/// </summary>
		public static readonly ClientScript UIHighlightEffect = new ClientScript("jquery.effects.highlight", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Pulsate">jQuery UI Pulsate effect</see>.
		/// </summary>
		public static readonly ClientScript UIPulsateEffect = new ClientScript("jquery.effects.pulsate", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Scale">jQuery UI Scale effect</see>.
		/// </summary>
		public static readonly ClientScript UIScaleEffect = new ClientScript("jquery.effects.scale", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Shake">jQuery UI Shake effect</see>.
		/// </summary>
		public static readonly ClientScript UIShakeEffect = new ClientScript("jquery.effects.shake", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Slide">jQuery UI Slide effect</see>.
		/// </summary>
		public static readonly ClientScript UISlideEffect = new ClientScript("jquery.effects.slide", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://docs.jquery.com/UI/Effects/Transfer">jQuery UI Transfer effect</see>.
		/// </summary>
		public static readonly ClientScript UITransferEffect = new ClientScript("jquery.effects.transfer", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/draggable/">jQuery UI Draggable interaction</see>.
		/// </summary>
		public static readonly ClientScript UIDraggableInteraction = new ClientScript("jquery.ui.draggable", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/droppable/">jQuery UI Droppable interaction</see>.
		/// </summary>
		public static readonly ClientScript UIDroppableInteraction = new ClientScript("jquery.droppable", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/resizable/">jQuery UI Resizable interaction</see>.
		/// </summary>
		public static readonly ClientScript UIResizableInteraction = new ClientScript("jquery.ui.resizable", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://jqueryui.com/demos/sortable/">jQuery UI Sortable interaction</see>.
		/// </summary>
		public static readonly ClientScript UISortableInteraction = new ClientScript("jquery.ui.sortable", uiUnified.name);

		/// <summary>
		/// The script library containing the <see href="http://gsgd.co.uk/sandbox/jquery/easing/"/>jQuery Easing Plugin</see> optionally used by the <see href="http://jqueryui.com/demos/accordion/">jQuery UI Accordion widget</see>.
		/// </summary>
		public static readonly ClientScript EasingPlugin = new ClientScript("jquery.easing");

		/// <summary>
		/// The script library containing code to make floating objects in the page float above dropdown list controls in IE6 using an iframe element.
		/// </summary>
		[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Bg", Justification = "Using Bg as abbreviation for background since it is the common name of the resource")]
		public static readonly ClientScript BgIFramePlugin = new ClientScript("jquery.bgiframe");

		/// <summary>
		/// The script library containing code to load and save cookies within certain widgets.
		/// </summary>
		public static readonly ClientScript CookiePlugin = new ClientScript("jquery.cookie");

		/// <summary>
		/// The script library containing code to parse metadata from elements.
		/// </summary>
		public static readonly ClientScript MetadataPlugin = new ClientScript("jquery.metadata");

		#endregion


		#region Fields

		private string name;
		private string substituteName;

		#endregion


		#region Constructors

		/// <summary>
		/// Creates a new instance of the <see cref="ClientScript"/> structure with no substitution.
		/// </summary>
		/// <param name="name">The invariant name of the script library.</param>
		public ClientScript(string name) : this(name, null) { }

		/// <summary>
		/// Creates a new instance of the <see cref="ClientScript"/> structure with an optional subtitution allowing multiple logical script libraries to be combined into a single combined library.
		/// </summary>
		/// <param name="name">The invariant name of the script library.</param>
		/// <param name="substituteName">The invariant name of a combined script library used in place of the atomic logical script library represented by the instance.</param>
		public ClientScript(string name, string substituteName) {
			if(name == null) throw new ArgumentNullException("name");
			if(name.Length == 0) throw new ArgumentException("Name must have a value.", "name");

			this.name = name;
			this.substituteName = substituteName;
		}

		#endregion


		#region Properties

		/// <summary>
		/// Gets the invariant name of the script library.
		/// </summary>
		public string Name {
			get { return name; }
		}

		/// <summary>
		/// Gets the invariant name of a combined script library used in place of the atomic logical library represented by the instance.
		/// </summary>
		public string SubstituteName {
			get { return substituteName; }
		}

		/// <summary>
		/// Gets the invariant name that will be used by the jQuery <see cref="Manager"/> to create the dynamic list of unique script libraries for the page.
		/// </summary>
		public string RegisterName {
			get {
				if(!string.IsNullOrEmpty(substituteName)) return substituteName;
				return name;
			}
		}

		/// <summary>
		/// Gets whether or not the instance has a no value.
		/// </summary>
		public bool IsEmpty {
			get { return name == null; }
		}

		#endregion


		#region Methods: Object management

		/// <summary>
		/// Determines whether or not the specified object is equal to the current <see cref="ClientScript"/> value.
		/// </summary>
		/// <param name="obj">The <see cref="Object"/> to compare.</param>
		/// <returns>Whether or not the provided object is equal.</returns>
		public override bool Equals(object obj) {
			if(obj is ClientScript) return this == (ClientScript)obj;
			return false;
		}

		/// <summary>
		/// Determines whether or not the specified ClientScript is equal to the current <see cref="ClientScript"/> value.
		/// </summary>
		/// <param name="other">The <see cref="ClientScript"/> to compare.</param>
		/// <returns>Whether or not the provided <see cref="ClientScript"/> value is equal.</returns>
		public bool Equals(ClientScript other) {
			return this == other;
		}

		/// <summary>
		/// Serves as a hash function for <see cref="ClientScript"/>.
		/// </summary>
		/// <returns>The hash value associated with the contained data.</returns>
		public override int GetHashCode() {
			if(IsEmpty) return 0;
			return RegisterName.GetHashCode();
		}

		/// <summary>
		/// Returns a <see cref="String"/> that represents the current <see cref="ClientScript"/> value.
		/// </summary>
		/// <returns>The string representation.</returns>
		public override string ToString() {
			if(IsEmpty) return string.Empty;
			return RegisterName.ToString();
		}

		/// <summary>
		/// Returns a literal JavaScript value used to represent the server value on the client.
		/// </summary>
		/// <returns>The client script value.</returns>
		public string ToClientSource() {
			if(IsEmpty) return ScriptBuilder.NullLiteral;
			return RegisterName.ToClientSource();
		}

		#endregion


		#region Operators

		/// <summary>
		/// Compares the equality of two <see cref="ClientScript"/> values.
		/// </summary>
		/// <param name="value0">The first value.</param>
		/// <param name="value1">The second value.</param>
		/// <returns>Whether or not the two values are equal.</returns>
		public static bool operator ==(ClientScript value0, ClientScript value1) {
			return value0.IsEmpty == value1.IsEmpty && value0.RegisterName == value1.RegisterName;
		}

		/// <summary>
		/// Compares the inequality of two <see cref="ClientScript"/> values.
		/// </summary>
		/// <param name="value0">The first value.</param>
		/// <param name="value1">The second value.</param>
		/// <returns>Whether or not the two values are distinct.</returns>
		public static bool operator !=(ClientScript value0, ClientScript value1) {
			return value0.IsEmpty != value1.IsEmpty || value0.RegisterName != value1.RegisterName;
		}

		#endregion


	}

}